/***************************************************************************
 *   Copyleft 2006-2007 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./Cuboid.h"

/**************************************************************
* Constructors                                                *
***************************************************************/
Cuboid::Cuboid(cFloat fXSize, cFloat fYSize, cFloat fZSize): Object3D(8, 12) {
	mColor = Color::ToWinColor(Color(1.0f, 1.0f, 0.0f));
	Update(fXSize, fYSize, fZSize);
	CreateEdges();
}
    
/**************************************************************
* Operators                                                   *
***************************************************************/


/**************************************************************
* Other helpful functions                                     *
***************************************************************/
cVoid Cuboid::CreateEdges() {
	mEdgeTable[0].mBegin = 0;
	mEdgeTable[0].mEnd = 1;
	mEdgeTable[1].mBegin = 0;
	mEdgeTable[1].mEnd = 3;
	mEdgeTable[2].mBegin = 0;
	mEdgeTable[2].mEnd = 4;

	mEdgeTable[3].mBegin = 2;
	mEdgeTable[3].mEnd = 6;
	mEdgeTable[4].mBegin = 2;
	mEdgeTable[4].mEnd = 3;
	mEdgeTable[5].mBegin = 2;
	mEdgeTable[5].mEnd = 1;

	mEdgeTable[6].mBegin = 5;
	mEdgeTable[6].mEnd = 1;
	mEdgeTable[7].mBegin = 5;
	mEdgeTable[7].mEnd = 6;
	mEdgeTable[8].mBegin = 5;
	mEdgeTable[8].mEnd = 4;

	mEdgeTable[9].mBegin = 7;
	mEdgeTable[9].mEnd = 6;
	mEdgeTable[10].mBegin = 7;
	mEdgeTable[10].mEnd = 3;
	mEdgeTable[11].mBegin = 7;
	mEdgeTable[11].mEnd = 4;
}

cVoid Cuboid::Update(cFloat fXSize, cFloat fYSize, cFloat fZSize) {
	cFloat fHalfXSize = fXSize / 2.0f;
	cFloat fHalfYSize = fYSize / 2.0f;
	cFloat fHalfZSize = fZSize / 2.0f;

	mVertexTable[0] = Point4D(-fHalfXSize, -fHalfYSize, fHalfZSize);
	mVertexTable[1] = Point4D(-fHalfXSize, -fHalfYSize, -fHalfZSize);
	mVertexTable[2] = Point4D(fHalfXSize, -fHalfYSize, -fHalfZSize);
	mVertexTable[3] = Point4D(fHalfXSize, -fHalfYSize, fHalfZSize);

	mVertexTable[4] = Point4D(-fHalfXSize, fHalfYSize, fHalfZSize);
	mVertexTable[5] = Point4D(-fHalfXSize, fHalfYSize, -fHalfZSize);
	mVertexTable[6] = Point4D(fHalfXSize, fHalfYSize, -fHalfZSize);
	mVertexTable[7] = Point4D(fHalfXSize, fHalfYSize, fHalfZSize);
}

cVoid Cuboid::Render(Renderer &renderer, Matrix4D &matrix, ProjectionPlane &plane) {
	Point4D a, b;

	if (mVisible) {
		if (mVertexTable && mEdgeTable) {
			for (cInt i = 0; i < mNrOfEdges; i++) {
				a = mVertexTable[mEdgeTable[i].mBegin];
				b = mVertexTable[mEdgeTable[i].mEnd];
				a = matrix * mMatrix * mObjectMatrix * a;
				b = matrix * mMatrix * mObjectMatrix * b;
				a.Normalize();
				b.Normalize();
				a.mX = a.mX + (renderer.GetWidth() >> 1);
				a.mY = a.mY + (renderer.GetHeight() >> 1);
				b.mX = b.mX + (renderer.GetWidth() >> 1);
				b.mY = b.mY + (renderer.GetHeight() >> 1);
				renderer.DrawLine(a, b, mColor);
			}
		}
	}
}

cVoid Cuboid::Render(Renderer &renderer, Matrix4D &matrix) {
	Point4D a, b;

	if (mVisible) {
		if (mVertexTable && mEdgeTable) {
			for (cInt i = 0; i < mNrOfEdges; i++) {
				a = mVertexTable[mEdgeTable[i].mBegin];
				b = mVertexTable[mEdgeTable[i].mEnd];
				a = matrix * mMatrix * mObjectMatrix * a;
				b = matrix * mMatrix * mObjectMatrix * b;
				a.Normalize();
				b.Normalize();
				a.mX = a.mX + (renderer.GetWidth() >> 1);
				a.mY = a.mY + (renderer.GetHeight() >> 1);
				b.mX = b.mX + (renderer.GetWidth() >> 1);
				b.mY = b.mY + (renderer.GetHeight() >> 1);
				renderer.DrawLine(a, b, mColor);
			}
		}
	}
}

cPoint Cuboid::GetBeginPoint(Matrix4D& matrix) {
	cPoint pBegin = {1000, 1000};
	Point4D a, b;

	if (mVertexTable) {
		for (cInt i = 0; i < mNrOfVertices; i++) {
			a = mVertexTable[i];
			a = matrix * mMatrix * mObjectMatrix * a;
			
			if (a.mX < pBegin.x) {
				pBegin.x = (cInt) a.mX;
			}
			if (a.mY < pBegin.y) {
				pBegin.y = (cInt) a.mY;
			}
		}
	}

	return pBegin;
}

cPoint Cuboid::GetDimensions(Matrix4D& matrix) {
	cPoint pDim = {-1000, -1000};
	Point4D a, b;

	if (mVertexTable) {
		for (cInt i = 0; i < mNrOfVertices; i++) {
			a = mVertexTable[i];
			a = matrix * mMatrix * mObjectMatrix * a;
			
			if (a.mX > pDim.x) {
				pDim.x = (cInt) a.mX;
			}
			if (a.mY > pDim.y) {
				pDim.y = (cInt) a.mY;
			}
		}
	}

	return pDim;
}

/*virtual*/ cChar* Cuboid::GetName() {
	return "Cuboid";
}